<?php

// mail engine
require_once 'phpMailer/class.phpmailer.php';

/**
 * @desc Mail draft.
 *
 */
class Kernel_Mail_Message extends Kernel_Component 
{

    /**
     * @desc Template name in DB.
     *
     * @var string
     */
    public $name;
    
    /**
    * @desc File template name.
    * 
    * @param string
    */
    public $template;

    /**
     * @desc Sender.
     *
     * @var string
     */
    public $from;

    /**
     * @desc Receiver(s). Can be string like "smb@host.com" or array like 
     * ("smb name"|0 => "smb@host.com", "anyb name"|1 => "anyb@host.com")
     *
     * @param mixed
     */
    public $to;

    /**
     * Let Subject be public in case of setting it manually
     *
     * @var string
     */
    public $subject; 

    /**
     * Путь к файлу шаблона для HTML-части
     *
     * @var string
     */
    protected $_html_template;

    /**
     * Путь к файлу шаблона для текстовой части
     *
     * @var string
     */
    protected $_text_template;

    /**
     * Набор переменных шаблона для формирования сообщения
     *
     * @var array
     */
    protected $_vars = array();
    
    /**
    * @desc Attachments list.
    * 
    * @param array
    */
    private $_attachments = array();
    
    /**
    * @desc Default mail charset.
    * 
    * @param string
    */
    private $_charset = 'utf-8';
    
    /**
    * @desc Composed email message body.
    * 
    * @param string
    */
    private $_body;
    
    
    /**
    * @desc Constructor.
    * 
    */
    public function __construct($params = array()) 
    {
        // get default "from" field
        $this->from = Kernel_Config::get('mail', 'from');
        
        parent::__construct($params);
        
        $this->_defineTemplate();
        // Set hosy by default
        $this->assign(array('HOST' => $this->_getHost()));
        
        return $this;
    }
    
    /**
     * Устанавливает набор переменных шаблона для формирования сообщения.
     *
     * @param   array   $vars
     * @return  Kernel_Mail_Message
     */
    public function assign($vars) 
    {
        $this->_vars = array_merge($this->_vars, $vars);
        return $this;
    }
    
    public function attachFiles($files) 
    {
        $this->_attachments = array_merge($this->_attachments, (array)$files);
        return $this;
    }
    
    /**
     * Отправляет сообщение, возвращает результат отправки.
     *
     * @return  boolean
     */
    public function send() 
    {
        $mail = new PHPMailer();
        $mail->CharSet = $this->_charset;
        
        // define from
        $mail->From = $this->_fromTemplate($this->from);
        $mail->FromName = null;
        
        // add reciever(s)
        foreach ((array)$this->to as $_to_name  => $_to_email) {
            $mail->AddAddress($this->_fromTemplate($_to_email), 
                !is_integer($_to_name) ? $this->_fromTemplate($_to_name) : null);
        }
        
        // subject
        $mail->Subject = $this->_fromTemplate($this->subject);
        
        // body
        if (!is_null($this->_text_template)) {
            $mail->Body = $this->_compose($this->_text_template);
            $mail->WordWrap = 80;
        }
        
        if (!is_null($this->_html_template)) {
            $mail->Body = $this->_compose($this->_html_template);
            $mail->IsHTML(true);
        }
        // store composed message
        $this->_body = $mail->Body;
        
        // attach files
        if (!empty($this->_attachments)) {
            while ($file = array_shift($this->_attachments)) {
                $mail->AddAttachment(Formbuilder_Utils::getFilePath() . $file);
            }
        }
        
        return $mail->Send();
    }
    
    public function getComposed() 
    {
        return $this->_body;
    }
    
    /**
     * Формирует фрагмент сообщения по указанному шаблону.
     *
     * @param   string  $template
     * @return  string
     */
    private function _compose($template) 
    {
        $engine = Kernel_Response_Html::createEngine();
        $engine->assign($this->_vars + array(
            'BASE_PATH' => BASE_PATH,
                '_lang' => __lang(), 
        ));
        
        return $engine->fetch($template);
    }

    /**
     * Формирует строку из шаблона. Как смарти, просто заменяет наименования
     * переменных на их значения.
     *
     * @param   string  $template
     * @return  string
     */
    private function _fromTemplate($template) 
    {
        return preg_replace('/\{\$([^\}]+)\}/e', '$this->_vars["$1"]', $template);
    }

    /**
     * @desc Set hosy by default. 
     *
     * @return  string
     */
    private function _getHost() 
    {
        return defined('BASE_PATH') 
            ? substr(preg_replace('/^https?:\/\//', '', constant('BASE_PATH')), 0, -1)
            : preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']);
    }

    /**
     * @desc Set template. 
     *
     */
    private function _defineTemplate() 
    {
        switch (!null) 
        {
            // if template name is specified get it from DB
            case $this->name : 
            {
                require_once KERNEL_PATH . '/plugins/resource.db.php';
                
                // читаем содержимое поля "subject" прямо в переменную — мы разбираем его без смарти
                $this->subject = smarty_resource_db_get($this->name, 'subject');
                
                // выставляем текстовый шаблон, если он непустой
                $this->_text_template = smarty_resource_db_defined($this->name, 'text')
                    ? 'db:' . $this->name . '.text' : null;
                
                // выставляем html-ный шаблон, если он непустой
                $this->_html_template = smarty_resource_db_defined($this->name, 'html')
                ? 'db:' . $this->name . '.html' : null;
                
                break;
            }
            
            // if template file is spesified 
            case $this->template : 
            {
                $this->_html_template = $this->template;
                
                break;
            }
            
            // tell about template absence obviously
            default : trigger_error('Template is not set', E_USER_ERROR);
        }
    }
    
}
